<!DOCTYPE html>
<html>
<head>
    <title> 浏览器拍照</title>
    <meta charset='utf-8'>
    <meta name="Author" content="renfufei@qq.com">
    <meta name="Description" content="inveted by: http://davidwalsh.name/browser-camera">
    <style type="text/css">
        #btnTakePhoto {
            width: 100px;
            height: 25px;
            font-size: 16px;
        }
    </style>
    
    <script>
        // 测试是否支持拍照
        function testCameraSecurity(){
            //
            var protocol_http = "http:";
            var protocol_https = "https:";
            var hostname_localhost = "localhost";
            var hostname_127 = "127.0.0.1";
            //
            var href = location.href;
            var hostname = location.hostname;
            var protocol = location.protocol;
            //
            var result = {
                unSupport : false, // 不支持
                unSafe : false,    // 不安全
                protocol : protocol,
                hostname : hostname,
                targetUrl : href
            };
            // 浏览器不支持!
            if(!window.navigator){
                result.unSupport = true;
                return result;
            }
            // file协议和https协议都不受拦截;
			//
            if(protocol_http == protocol){
                //
                if(hostname_localhost == hostname || hostname_127 == hostname){
                    // localhost和127也不受拦截.
                    return result;
                } else {
                    // 其他的 http 域名不安全。不受支持;
                    var httpsHref = href.replace(protocol_http, protocol_https);
                    //
                    result.unSafe = true;
                    result.targetUrl = httpsHref;
                    return result;
                }
            }
            //
            return result;
        };
        // 测试
        var result = testCameraSecurity();
        if(result.unSupport){
            window.alert("浏览器不支持拍照!");
        } else if(result.unSafe){
            var cfmFlag = window.confirm("["+result.protocol+"//"+result.hostname+"]受到安全限制,是否跳转到https?");
            if(cfmFlag){
                window.location.replace(result.targetUrl);
            }
        }
    </script>
</head>

<body>

<div>
    <!--
    声明： 此div应该在允许使用webcam，网络摄像头之后动态生成
    宽高： 640 *480,当然，可以动态控制啦!
    -->
    <!--
Ideally these elements aren't created until it's confirmed that the
client supports video/camera, but for the sake of illustrating the
elements involved, they are created with markup (not JavaScript)
    -->
    <video id="srcVideo" width="640" height="480" autoplay></video>
    <button id="btnTakePhoto">拍照</button>
    <canvas id="targetCanvas" width="640" height="480"></canvas>
</div>


<script>
    //
    // 参数，最大高度  
    var MAX_HEIGHT = 100;
    //
    // 把image 转换为 canvas对象
    function convertImageToCanvas(image) {
        // 创建canvas DOM元素，并设置其宽高和图片一样
        var canvas = document.createElement("canvas");
        canvas.width = image.width;
        canvas.height = image.height;
        // 坐标(0,0) 表示从此处开始绘制，相当于偏移。
        canvas.getContext("2d").drawImage(image, 0, 0);

        return canvas;
    }
    // 从 canvas 提取图片 image
    function convertCanvasToImage(canvas) {
        //新Image对象，可以理解为DOM
        var image = new Image();
        // canvas.toDataURL 返回的是一串Base64编码的URL，当然,浏览器自己肯定支持
        // 指定格式 PNG
        image.src = canvas.toDataURL("image/png");
        return image;
    }
    ;
    // 渲染  
    function render(src) {
        // 创建一个 Image 对象  
        var image = new Image();
        // 绑定 load 事件处理器，加载完成后执行  
        image.onload = function () {
            // 获取 canvas DOM 对象  
            var canvas = document.getElementById("myCanvas");
            // 如果高度超标  
            if (image.height > MAX_HEIGHT) {
                // 宽度等比例缩放 *=  
                image.width *= MAX_HEIGHT / image.height;
                image.height = MAX_HEIGHT;
            }
            // 获取 canvas的 2d 环境对象,  
            // 可以理解Context是管理员，canvas是房子  
            var ctx = canvas.getContext("2d");
            // canvas清屏  
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            // 重置canvas宽高  
            canvas.width = image.width;
            canvas.height = image.height;
            // 将图像绘制到canvas上  
            ctx.drawImage(image, 0, 0, image.width, image.height);
            // !!! 注意，image 没有加入到 dom之中  
        };
        // 设置src属性，浏览器会自动加载。  
        // 记住必须先绑定事件，才能设置src属性，否则会出同步问题。  
        image.src = src;
    }
    ;
    // 加载 图像文件(url路径)  
    function loadImage(src) {
        // 过滤掉 非 image 类型的文件  
        if (!src.type.match(/image.*/)) {
            if (window.console) {
                console.log("选择的文件类型不是图片: ", src.type);
            } else {
                window.confirm("只能选择图片文件");
            }
            return;
        }

        // 创建 FileReader 对象 并调用 render 函数来完成渲染.  
        var reader = new FileReader();
        // 绑定load事件自动回调函数  
        reader.onload = function (e) {
            // 调用前面的 render 函数  
            render(e.target.result);
        };
        // 读取文件内容  
        reader.readAsDataURL(src);
    }
    ;

    // 上传图片，jQuery版  
    function sendImage() {
        // 获取 canvas DOM 对象
        var canvas = document.getElementById("myCanvas");
        // 获取Base64编码后的图像数据，格式是字符串
        // "data:image/png;base64,"开头,需要在客户端或者服务器端将其去掉，后面的部分可以直接写入文件。
        var dataurl = canvas.toDataURL("image/png");
        // 为安全 对URI进行编码
        // data%3Aimage%2Fpng%3Bbase64%2C 开头
        var imagedata = encodeURIComponent(dataurl);
        //var url = $("#form").attr("action");
        // 1. 如果form表单不好处理,可以使用某个hidden隐藏域来设置请求地址
        // <input type="hidden" name="action" value="receive.jsp" />
        var url = $("input[name='action']").val();
        // 2. 也可以直接用某个dom对象的属性来获取
        // <input id="imageaction" type="hidden" action="receive.jsp">
        // var url = $("#imageaction").attr("action");

        // 因为是string，所以服务器需要对数据进行转码，写文件操作等。
        // 个人约定，所有http参数名字全部小写
        console.log(dataurl);
        //console.log(imagedata);
        var data = {
            imagename: "myImage.png",
            imagedata: imagedata
        };
        jQuery.ajax({
            url: url,
            data: data,
            type: "POST",
            // 期待的返回值类型
            dataType: "json",
            complete: function (xhr, result) {
                //console.log(xhr.responseText);
                var $tip2 = $("#tip2");
                if (!xhr) {
                    $tip2.text('网络连接失败!');
                    return false;
                }

                var text = xhr.responseText;
                if (!text) {
                    $tip2.text('网络错误!');
                    return false;
                }

                var json = eval("(" + text + ")");
                if (!json) {
                    $tip2.text('解析错误!');
                    return false;
                } else {
                    $tip2.text(json.message);
                }
                //console.dir(json);
                //console.log(xhr.responseText);
            }
        });
    }
    ;

    // 设置事件监听，DOM内容加载完成，和jQuery的$.ready() 效果差不多。
    window.addEventListener("DOMContentLoaded", function () {
        // canvas 元素将用于抓拍
        var canvas = document.getElementById("targetCanvas");
        var context = canvas.getContext("2d");
        // video 元素，将用于接收并播放摄像头 的数据流
        var video = document.getElementById("srcVideo");
        var videoObj = {"video": true};
        // 一个出错的回调函数，在控制台打印出错信息
        function errBack(error) {
                    if ("object" === typeof window.console) {
                        console.log("Video capture error: ", error.code);
                    }
        };

        // Put video listeners into place
        // 针对标准的浏览器
        if (navigator.getUserMedia) { // Standard
            navigator.getUserMedia(videoObj, function (stream) {
                video.srcObject = stream;
                video.play();
            }, errBack);
        } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
            navigator.webkitGetUserMedia(videoObj, function (stream) {
                video.src = window.webkitURL.createObjectURL(stream);
                video.play();
            }, errBack);
        }
        // 对拍照按钮的事件监听
        document.getElementById("btnTakePhoto").addEventListener("click", function () {
            // 画到画布上
            context.drawImage(video, 0, 0, 640, 480);
        });
    }, false);
</script>
</body>
</html>